//
// Created by yonghu0 on 25-10-19.
//

#include "MongoDataBase.h"
#include "../include/snowflake.hpp"
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mutex>
#include <cstdint>
#include <algorithm>

#include "Judger.h"

using bsoncxx::builder::basic::make_document;
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::stream::document;
using bsoncxx::builder::stream::open_array;
using bsoncxx::builder::stream::close_array;
using bsoncxx::builder::stream::open_document;
using bsoncxx::builder::stream::close_document;
using bsoncxx::builder::stream::finalize;

// 雪花算法
using snowflake_t = snowflake<1534832906275L, std::mutex>;
snowflake_t uuid;

// 获取时间
std::string GetTime()
{
    time_t t = time(nullptr);
    struct tm *now = localtime(&t);
    char str[50] = {0};
    strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", now);
    return (std::string) str;
}

int64_t MoDB::GetMaxId(std::string name)
{
    auto client = pool.acquire();
    mongocxx::collection coll = (*client)["OJ"][name.data()];

    bsoncxx::builder::stream::document document{};
    mongocxx::pipeline pipe;
    pipe.sort({make_document(kvp("_id", -1))});
    pipe.limit(1);
    mongocxx::cursor cursor = coll.aggregate(pipe);

    // 如果没找到，说明集合中没有数据
    if (cursor.begin() == cursor.end())
        return 0;

    Json::Value jsonvalue;
    Json::Reader reader;
    for (auto doc: cursor)
    {
        reader.parse(bsoncxx::to_json(doc), jsonvalue);
    }

    int64_t id = stoll(jsonvalue["_id"].asString());
    return id;
}

MoDB::MoDB(): uri(Config::GetInstance().GetValue("mongodb_connect")),
              pool(uri)
{
    m_problemid = GetMaxId("Problem");
    int64_t announcementid = GetMaxId("Announcement");
    int64_t discussid = GetMaxId("Discuss");
    int64_t solutionid = GetMaxId("Solution");
    m_articleid = std::max(announcementid, std::max(discussid, solutionid));
    m_commentid = GetMaxId("Comment");
    m_statusrecordid = GetMaxId("StatusRecord");
}

MoDB::~MoDB()
{
}

MoDB *MoDB::GetInstance()
{
    static MoDB MoDB;
    return &MoDB;
}

Json::Value MoDB::RegisterUser(Json::Value registerjson)
{
    Json::Value resjson;
    try
    {
        std::string nickname = registerjson["NickName"].asString();
        std::string account = registerjson["Account"].asString();
        std::string password = registerjson["PassWord"].asString();
        std::string personalprofile = registerjson["PersonalProfile"].asString();
        std::string school = registerjson["School"].asString();
        std::string major = registerjson["Major"].asString();

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];

        //判断account是否存在
        mongocxx::cursor cursor = usercoll.find(make_document(kvp("Account", account)));
        if (cursor.begin() != cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "用户名存在";
            return resjson;
        }
        uuid.init(1, 1);
        int64_t id = uuid.nextid();

        std::string jointime = GetTime();
        std::string avatar = "http://192.168.30.128:8081/image/1";

        //插入用户
        bsoncxx::builder::stream::document document{};
        document
                << "_id" << id
                << "Avatar" << avatar
                << "NickName" << nickname
                << "Account" << account
                << "PassWord" << password
                << "PersonalProfile" << personalprofile
                << "School" << school
                << "Major" << major
                << "JoinTime" << jointime
                << "CommentLikes" << open_array << close_array
                << "Solves" << open_array << close_array
                << "ACNum" << 0
                << "SubmitNum" << 0
                << "Authority" << 3;
        auto result = usercoll.insert_one(document.view());
        if ((*result).result().inserted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库插入失败！";
            return resjson;
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        resjson["_id"] = (Json::Int64) id;
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::LoginUser(Json::Value loginjson)
{
    Json::Value resjson;
    try
    {
        std::string account = loginjson["Account"].asString();
        std::string password = loginjson["PassWord"].asString();

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];
        mongocxx::pipeline pipe;

        bsoncxx::builder::stream::document document{};
        document
                << "Account" << account
                << "PassWord" << password;
        pipe.match(document.view());

        document.clear();
        document
                << "_id" << 1
                << "NickName" << 1
                << "Avatar" << 1
                << "CommentLikes" << 1
                << "Solves" << 1
                << "Authority" << 1;
        pipe.project(document.view());

        mongocxx::cursor cursor = usercoll.aggregate(pipe);
        //查不到
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "用户名或密码错误！";
            return resjson;
        }
        //查找成功
        for (auto &doc: cursor)
        {
            Json::Reader reader;
            Json::Value json;
            reader.parse(bsoncxx::to_json(doc), json);
            resjson["Info"] = json;
        }
        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectUserInfo(Json::Value selectjson)
{
    Json::Value resjson;
    try
    {
        int64_t userid = stoll(selectjson["UserId"].asString());

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];
        mongocxx::pipeline pipe;

        pipe.match(make_document(kvp("_id", userid)));

        bsoncxx::builder::stream::document document{};
        document
                << "Avatar" << 1
                << "NickName" << 1
                << "PersonalProfile" << 1
                << "School" << 1
                << "Major" << 1
                << "JoinTime" << 1
                << "Solves" << 1
                << "ACNum" << 1
                << "SubmitNum" << 1;
        pipe.project(document.view());

        auto cursor = usercoll.aggregate(pipe);
        //查不到
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "没有这个用户";
            return resjson;
        }
        //查到了
        for (auto &doc: cursor)
        {
            Json::Reader reader;
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::UpdateUser(Json::Value updatejson)
{
    Json::Value resjson;
    try
    {
        int64_t userid = stoll(updatejson["UserId"].asString());
        std::string avatar = updatejson["Avatar"].asString();
        std::string personalprofile = updatejson["PersonalProfile"].asString();
        std::string school = updatejson["School"].asString();
        std::string major = updatejson["Major"].asString();

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];

        bsoncxx::builder::stream::document document{};
        document
                << "$set" << open_document
                << "Avatar" << avatar
                << "PersonalProfile" << personalprofile
                << "School" << school
                << "Major" << major
                << close_document;
        auto result = usercoll.update_one(make_document(kvp("_id", userid)), document.view());

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::GetUserUpdateInfo(Json::Value getjson)
{
    Json::Value resjson;
    try
    {
        int64_t userid = stoll(getjson["UserId"].asString());

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];
        mongocxx::pipeline pipe;

        pipe.match(make_document(kvp("_id", userid)));

        bsoncxx::builder::stream::document document{};
        document
                << "Avatar" << 1
                << "NickName" << 1
                << "PersonalProfile" << 1
                << "School" << 1
                << "Major" << 1;
        pipe.project(document.view());

        auto cursor = usercoll.aggregate(pipe);
        //查不到
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "没有这个用户";
            return resjson;
        }
        //查到了
        for (auto &doc: cursor)
        {
            Json::Reader reader;
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::DeleteUser(Json::Value deletejson)
{
    Json::Value resjson;
    try
    {
        int64_t userid = stoll(deletejson["UserId"].asString());

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];
        auto result = usercoll.delete_one(make_document(kvp("_id", userid)));

        //查不到
        if ((*result).result().deleted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库删除失败！";
            return resjson;
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::GetUserlistInfo(Json::Value getjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(getjson["Page"].asString());
        int pagesize = stoi(getjson["PageSize"].asString());
        int skipnum = (page - 1) * pagesize;
        int limitnum = pagesize;

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];
        mongocxx::pipeline pipe;

        pipe.skip(skipnum);
        pipe.limit(limitnum);
        bsoncxx::builder::stream::document document{};
        document
                << "NickName" << 1
                << "PersonalProfile" << 1
                << "School" << 1
                << "Major" << 1
                << "JoinTime" << 1;
        pipe.project(document.view());

        auto cursor = usercoll.aggregate(pipe);

        for (auto &doc: cursor)
        {
            Json::Reader reader;
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::RankUser(Json::Value rankjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(rankjson["Page"].asString());
        int pagesize = stoi(rankjson["PageSize"].asString());
        int skipnum = (page - 1) * pagesize;
        int limitnum = pagesize;

        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];
        mongocxx::pipeline pipe, pipeto;
        Json::Reader reader;

        pipeto.count("TotalNum");
        auto cursor = usercoll.aggregate(pipeto);
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        bsoncxx::builder::stream::document document{};
        document
                << "ACNum" << -1
                << "SubmitNum" << 1;
        pipe.sort(document.view());
        pipe.skip(skipnum);
        pipe.limit(limitnum);

        document.clear();
        document
                << "Avatar" << 1
                << "NickName" << 1
                << "PersonalProfile" << 1
                << "SubmitNum" << 1
                << "ACNum" << 1;
        pipe.project(document.view());

        cursor = usercoll.aggregate(pipe);
        //如果没有用户
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Success";
            resjson["Reason"] = "";
            return resjson;
        }

        for (auto &doc: cursor)
        {
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        int rank = (page - 1) * pagesize + 1;
        for (int i = 0; i < resjson["ArrayInfo"].size(); i++)
        {
            resjson["ArrayInfo"][i]["Rank"] = rank;
            rank++;
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::TokenLoginUser(Json::Value loginjson)
{
    Json::Value resjson;
    try
    {
        int64_t userid = stoll(loginjson["UserId"].asString());
        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];

        mongocxx::pipeline pipe;
        bsoncxx::builder::stream::document document{};
        document
                << "_id" << userid;
        pipe.match(document.view());

        document.clear();
        document
                << "Avatar" << 1
                << "NickName" << 1
                << "CommentLikes" << 1
                << "Solves" << 1
                << "Authority" << 1;

        pipe.project(document.view());

        mongocxx::cursor cursor = usercoll.aggregate(pipe);
        // 匹配失败
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "用户ID错误！";
            return resjson;
        }
        // 匹配成功
        Json::Reader reader;
        for (auto doc: cursor)
        {
            Json::Value jsonvalue;
            reader.parse(bsoncxx::to_json(doc), jsonvalue);
            resjson["Info"] = jsonvalue;
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::SelectProblem(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t problemid = stoll(queryjson["ProblemId"].asString());

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];
        mongocxx::pipeline pipe;

        pipe.match(make_document(kvp("_id", problemid)));

        bsoncxx::builder::stream::document document{};
        document
                << "Title" << 1
                << "Description" << 1
                << "TimeLimit" << 1
                << "MemoryLimit" << 1
                << "JudgeNum" << 1
                << "SubmitNum" << 1
                << "ACNum" << 1
                << "UserNickName" << 1
                << "Tags" << 1;
        pipe.project(document.view());

        auto cursor = problemcoll.aggregate(pipe);
        //查不到
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库查不到这个题目";
            return resjson;
        }
        //查到了
        for (auto &doc: cursor)
        {
            Json::Reader reader;
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectProblemList(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        std::string title = queryjson["SearchInfo"]["Title"].asString();
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;
        int limit = pagesize;

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];
        mongocxx::pipeline pipe, pipeto;
        bsoncxx::builder::stream::document document{};

        if (queryjson["SearchInfo"]["Id"].asString().size() > 0)
        {
            int64_t problemid = stoll(queryjson["SearchInfo"]["Id"].asString());
            pipe.match(make_document(kvp("_id", problemid)));
            pipeto.match(make_document(kvp("_id", problemid)));
        }
        if (title.size() > 0)
        {
            document
                    << "Title" << open_document
                    << "$regex" << title
                    << close_document;
            pipe.match(document.view());
            pipeto.match(document.view());
            document.clear();
        }
        if (queryjson["SearchInfo"]["Tags"].size() > 0)
        {
            auto in_array = document
                            << "Tags" << open_document
                            << "$in" << open_array;
            for (unsigned int i = 0; i < queryjson["SearchInfo"]["Tags"].size(); i++)
            {
                in_array = in_array
                           << queryjson["SearchInfo"]["Tags"][i].asString();
            }
            bsoncxx::document::value doc = in_array << close_array << close_document << finalize;
            pipe.match(doc.view());
            pipeto.match(doc.view());
            document.clear();
        }

        pipeto.count("TotalNum");
        auto cursor = problemcoll.aggregate(pipeto);
        Json::Reader reader;
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        document
                << "ProblemId"
                << "$_id"
                << "Title" << 1
                << "SubmitNum" << 1
                << "CENum" << 1
                << "ACNum" << 1
                << "WANum" << 1
                << "RENum" << 1
                << "TLENum" << 1
                << "MLENum" << 1
                << "SENum" << 1
                << "Tags" << 1;
        pipe.project(document.view());
        pipe.sort(make_document(kvp("_id", 1)));
        pipe.skip(skip);
        pipe.limit(limit);

        cursor = problemcoll.aggregate(pipe);
        for (auto &doc: cursor)
        {
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectProblemListByAdmin(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];

        Json::Reader reader;
        mongocxx::pipeline pipe, pipetot;
        bsoncxx::builder::stream::document document{};

        // 获取总条数
        pipetot.count("TotalNum");
        mongocxx::cursor cursor = problemcoll.aggregate(pipetot);
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        // 排序
        pipe.sort({make_document(kvp("_id", 1))});
        // 跳过
        pipe.skip(skip);
        // 限制
        pipe.limit(pagesize);
        // 进行
        document
                << "ProblemId"
                << "$_id"
                << "Title" << 1
                << "SubmitNum" << 1
                << "CENum" << 1
                << "ACNum" << 1
                << "WANum" << 1
                << "RENum" << 1
                << "TLENum" << 1
                << "MLENum" << 1
                << "SENum" << 1
                << "Tags" << 1;
        pipe.project(document.view());

        Json::Value arryjson;
        cursor = problemcoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            Json::Value jsonvalue;
            reader.parse(bsoncxx::to_json(doc), jsonvalue);
            arryjson.append(jsonvalue);
        }
        resjson["ArrayInfo"] = arryjson;
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库出错啦！";
        return resjson;
    }
}

Json::Value MoDB::SelectProblemInfoByAdmin(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t problemid = stoll(queryjson["ProblemId"].asString());

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];

        bsoncxx::builder::stream::document document{};
        mongocxx::pipeline pipe;
        pipe.match({make_document(kvp("_id", problemid))});

        document
                << "Title" << 1
                << "Description" << 1
                << "TimeLimit" << 1
                << "MemoryLimit" << 1
                << "JudgeNum" << 1
                << "UserNickName" << 1
                << "Tags" << 1;
        pipe.project(document.view());

        Json::Reader reader;

        mongocxx::cursor cursor = problemcoll.aggregate(pipe);

        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库未查询到该信息！";
            return resjson;
        }

        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::InsertProblem(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        ++m_problemid;
        int64_t problemid = m_problemid;
        std::string title = queryjson["Title"].asString();
        std::string description = queryjson["Description"].asString();
        std::string usernickname = queryjson["UserNickName"].asString();
        int judgenum = stoi(queryjson["JudgeNum"].asString());
        int timelimit = stoi(queryjson["TimeLimit"].asString());
        int memorylimit = stoi(queryjson["MemoryLimit"].asString());

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];

        //插入用户
        bsoncxx::builder::stream::document document{};
        auto in_array = document
                        << "_id" << problemid
                        << "Title" << title
                        << "Description" << description
                        << "TimeLimit" << timelimit
                        << "MemoryLimit" << memorylimit
                        << "JudgeNum" << judgenum
                        << "SubmitNum" << 0
                        << "CENum" << 0
                        << "ACNum" << 0
                        << "WANum" << 0
                        << "RENum" << 0
                        << "TLENum" << 0
                        << "MLENum" << 0
                        << "SENum" << 0
                        << "UserNickName" << usernickname
                        << "Tags" << open_array;
        for (int i = 0; i < queryjson["Tags"].size(); i++)
        {
            in_array << queryjson["Tags"][i].asString();
        }
        bsoncxx::document::value doc = in_array << close_array << finalize;

        auto result = problemcoll.insert_one(doc.view());
        if ((*result).result().inserted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库插入失败！";
            return resjson;
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        resjson["_id"] = (Json::Int64) problemid;
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::UpdateProblem(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t _id = stoll(queryjson["ProblemId"].asString());
        std::string title = queryjson["Title"].asString();
        std::string description = queryjson["Description"].asString();
        std::string usernickname = queryjson["UserNickName"].asString();
        int judgenum = stoi(queryjson["JudgeNum"].asString());
        int timelimit = stoi(queryjson["TimeLimit"].asString());
        int memorylimit = stoi(queryjson["MemoryLimit"].asString());

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];

        //插入用户
        bsoncxx::builder::stream::document document{};
        auto in_array = document
                        << "$set" << open_document
                        << "Title" << title.data()
                        << "Description" << description.data()
                        << "TimeLimit" << timelimit
                        << "MemoryLimit" << memorylimit
                        << "JudgeNum" << judgenum
                        << "UserNickName" << usernickname.data()
                        << "Tags" << open_array;
        for (int i = 0; i < queryjson["Tags"].size(); i++)
        {
            in_array << queryjson["Tags"][i].asString();
        }
        bsoncxx::document::value doc = in_array << close_array << close_document << finalize;

        problemcoll.update_one({make_document(kvp("_id", _id))}, doc.view());

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        resjson["_id"] = (Json::Int64) _id;
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::DeleteProblem(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t problemid = stoll(queryjson["ProblemId"].asString());

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];

        auto result = problemcoll.delete_one({make_document(kvp("_id", problemid))});

        if ((*result).deleted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库删除失败！";
            return resjson;
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::GetProblemTags()
{
    auto client = pool.acquire();
    mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];
    mongocxx::cursor cursor = problemcoll.distinct({"Tags"}, {});
    Json::Reader reader;
    Json::Value resjson;
    for (auto doc: cursor)
    {
        reader.parse(bsoncxx::to_json(doc), resjson);
    }
    return resjson;
}

Json::Value MoDB::SelectAnnouncementList(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;
        int limit = pagesize;

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];
        mongocxx::pipeline pipe, pipeto;
        bsoncxx::builder::stream::document document{};

        pipeto.count("TotalNum");
        auto cursor = announcementcoll.aggregate(pipeto);
        Json::Reader reader;
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        document
                << "CreateTime" << -1
                << "Level" << -1;
        pipe.sort(document.view());
        pipe.skip(skip);
        pipe.limit(limit);

        document.clear();
        document
                << "Title" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1;
        pipe.project(document.view());

        cursor = announcementcoll.aggregate(pipe);
        for (auto &doc: cursor)
        {
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectAnnouncementListByAdmin(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;
        int limit = pagesize;

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];
        mongocxx::pipeline pipe, pipeto;
        bsoncxx::builder::stream::document document{};

        pipeto.count("TotalNum");
        auto cursor = announcementcoll.aggregate(pipeto);
        Json::Reader reader;
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        document
                << "CreateTime" << -1
                << "Level" << -1;
        pipe.sort(document.view());
        pipe.skip(skip);
        pipe.limit(limit);

        document.clear();
        document
                << "Title" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1;
        pipe.project(document.view());

        cursor = announcementcoll.aggregate(pipe);
        for (auto &doc: cursor)
        {
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectAnnouncement(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t announcementid = stoll(queryjson["AnnouncementId"].asString());

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];
        mongocxx::pipeline pipe;

        //此时用户浏览了公告，更新浏览量
        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "Views" << 1
                << close_document;
        announcementcoll.update_one(make_document(kvp("_id", announcementid)),
                                    document.view());

        pipe.match(make_document(kvp("_id", announcementid)));

        document.clear();
        document
                << "Title" << 1
                << "Content" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1
                << "UpdateTime" << 1;
        pipe.project(document.view());

        auto cursor = announcementcoll.aggregate(pipe);
        //查不到
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库查不到这个公告";
            return resjson;
        }
        //查到了
        for (auto &doc: cursor)
        {
            Json::Reader reader;
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectAnnouncementByEdit(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t announcementid = stoll(queryjson["AnnouncementId"].asString());

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];
        mongocxx::pipeline pipe;
        bsoncxx::builder::stream::document document{};

        pipe.match(make_document(kvp("_id", announcementid)));

        document
                << "Title" << 1
                << "Content" << 1
                << "Level" << 1;
        pipe.project(document.view());

        auto cursor = announcementcoll.aggregate(pipe);
        //查不到
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库查不到这个公告";
            return resjson;
        }
        //查到了
        for (auto &doc: cursor)
        {
            Json::Reader reader;
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::InsertAnnouncement(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        ++m_articleid;
        int64_t articleid = m_articleid;
        std::string title = queryjson["Title"].asString();
        std::string content = queryjson["Content"].asString();
        int64_t userid = stoll(queryjson["UserId"].asString());
        int level = queryjson["Level"].asInt();

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];

        //插入用户
        bsoncxx::builder::stream::document document{};
        document
                << "_id" << articleid
                << "Title" << title
                << "Content" << content
                << "UserId" << userid
                << "Views" << 0
                << "Comments" << 0
                << "Level" << level
                << "CreateTime" << GetTime()
                << "UpdateTime" << GetTime();

        auto result = announcementcoll.insert_one(document.view());
        if ((*result).result().inserted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库插入失败！";
            return resjson;
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::UpdateAnnouncement(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t announcementid = stoll(queryjson["AnnouncementId"].asString());
        std::string title = queryjson["Title"].asString();
        std::string content = queryjson["Content"].asString();
        int level = queryjson["Level"].asInt();

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];

        bsoncxx::builder::stream::document document{};
        document
                << "$set" << open_document
                << "Title" << title
                << "Content" << content
                << "Level" << level
                << "UpdateTime" << GetTime()
                << close_document;

        announcementcoll.update_one({make_document(kvp("_id", announcementid))}, document.view());

        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::DeleteAnnouncement(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t announcementid = stoll(queryjson["AnnouncementId"].asString());

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];

        auto result = announcementcoll.delete_one({make_document(kvp("_id", announcementid))});
        if ((*result).deleted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库删除失败！";
            return resjson;
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

bool MoDB::UpdateAnnouncementComments(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t articleId = stoll(queryjson["ArticleId"].asString());
        int num = queryjson["Num"].asInt();

        auto client = pool.acquire();
        mongocxx::collection announcementcoll = (*client)["OJ"]["Announcement"];
        mongocxx::pipeline pipe;

        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "Comments" << num
                << close_document;
        announcementcoll.update_one(make_document(kvp("_id", articleId)),
                                    document.view());
        return true;
    } catch (std::exception &e)
    {
        return false;
    }
}

Json::Value MoDB::SelectDiscussList(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        Json::Value searchinfo = queryjson["SearchInfo"];
        int64_t parentid = stoll(searchinfo["ParentId"].asString());
        int64_t userid = stoll(searchinfo["UserId"].asString());
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;
        int limit = pagesize;

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];
        mongocxx::pipeline pipe, pipetot;
        bsoncxx::builder::stream::document document{};

        if (parentid > 0)
        {
            pipe.match({make_document(kvp("ParentId", parentid))});
            pipetot.match({make_document(kvp("ParentId", parentid))});
        }

        if (userid > 0)
        {
            pipe.match({make_document(kvp("UserId", userid))});
            pipetot.match({make_document(kvp("UserId", userid))});
        }

        if (parentid == 0 && userid == 0)
        {
            pipe.match({make_document(kvp("ParentId", 0))});
            pipetot.match({make_document(kvp("ParentId", 0))});
        }

        pipetot.count("TotalNum");
        auto cursor = discusscoll.aggregate(pipetot);
        Json::Reader reader;
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        document
                << "from" << "User"
                << "localField" << "UserId"
                << "foreignField" << "_id"
                << "as" << "User";
        pipe.lookup(document.view());

        document.clear();
        document
                << "Title" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1
                << "User.Avatar" << 1
                << "User.NickName" << 1;
        pipe.project(document.view());

        pipe.sort({make_document(kvp("CreateTime", -1))});
        pipe.skip(skip);
        pipe.limit(limit);

        cursor = discusscoll.aggregate(pipe);
        for (auto &doc: cursor)
        {
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectDiscussListByAdmin(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;
        int limit = pagesize;

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];
        mongocxx::pipeline pipe, pipetot;
        bsoncxx::builder::stream::document document{};

        pipetot.count("TotalNum");
        auto cursor = discusscoll.aggregate(pipetot);
        Json::Reader reader;
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        document
                << "from" << "User"
                << "localField" << "UserId"
                << "foreignField" << "_id"
                << "as" << "User";
        pipe.lookup(document.view());

        document.clear();
        document
                << "Title" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1
                << "UserId" << 1
                << "User.Avatar" << 1
                << "User.NickName" << 1;
        pipe.project(document.view());

        pipe.sort({make_document(kvp("CreateTime", -1))});
        pipe.skip(skip);
        pipe.limit(limit);

        cursor = discusscoll.aggregate(pipe);
        for (auto &doc: cursor)
        {
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::SelectDiscuss(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t discussid = stoll(queryjson["DiscussId"].asString());

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];
        // 浏览量加一
        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "Views" << 1 << close_document;
        discusscoll.update_one({make_document(kvp("_id", discussid))}, document.view());

        // 查询Content
        mongocxx::pipeline pipe;
        pipe.match({make_document(kvp("_id", discussid))});

        document.clear();
        document
                << "from" << "User"
                << "localField" << "UserId"
                << "foreignField" << "_id"
                << "as" << "User";
        pipe.lookup(document.view());

        document.clear();
        document
                << "Title" << 1
                << "Content" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1
                << "UpdateTime" << 1
                << "User._id" << 1
                << "User.Avatar" << 1
                << "User.NickName" << 1;
        pipe.project(document.view());
        mongocxx::cursor cursor = discusscoll.aggregate(pipe);

        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库未查询到数据!";
            return resjson;
        }

        Json::Reader reader;
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::SelectDiscussByEdit(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t discussid = stoll(queryjson["DiscussId"].asString());

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];

        bsoncxx::builder::stream::document document{};
        mongocxx::pipeline pipe;
        pipe.match({make_document(kvp("_id", discussid))});
        document
                << "Title" << 1
                << "UserId" << 1
                << "Content" << 1;
        pipe.project(document.view());
        mongocxx::cursor cursor = discusscoll.aggregate(pipe);

        Json::Reader reader;

        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库未查询到数据！";
            return resjson;
        }
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::InsertDiscuss(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        ++m_articleid;
        int64_t articleid = m_articleid;
        std::string title = queryjson["Title"].asString();
        std::string content = queryjson["Content"].asString();
        int64_t parentid = stoll(queryjson["ParentId"].asString());
        int64_t userid = stoll(queryjson["UserId"].asString());

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];

        //插入用户
        bsoncxx::builder::stream::document document{};
        document
                << "_id" << articleid
                << "Title" << title
                << "Content" << content
                << "ParentId" << parentid
                << "UserId" << userid
                << "Views" << 0
                << "Comments" << 0
                << "CreateTime" << GetTime()
                << "UpdateTime" << GetTime();

        auto result = discusscoll.insert_one(document.view());
        if ((*result).result().inserted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库插入失败！";
            return resjson;
        }

        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库错误!";
        return resjson;
    }
}

Json::Value MoDB::UpdateDiscuss(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t discussid = stoll(queryjson["DiscussId"].asString());
        std::string title = queryjson["Title"].asString();
        std::string content = queryjson["Content"].asString();

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];

        bsoncxx::builder::stream::document document{};
        document
                << "$set" << open_document
                << "Title" << title
                << "Content" << content
                << "UpdateTime" << GetTime()
                << close_document;

        discusscoll.update_one({make_document(kvp("_id", discussid))}, document.view());

        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::DeleteDiscuss(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t discussid = stoll(queryjson["DiscussId"].asString());

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];

        auto result = discusscoll.delete_one({make_document(kvp("_id", discussid))});

        if ((*result).deleted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库删除失败！";
            return resjson;
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::UpdateDiscussComments(Json::Value queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t articleId = stoll(queryjson["ArticleId"].asString());
        int num = queryjson["Num"].asInt();

        auto client = pool.acquire();
        mongocxx::collection discusscoll = (*client)["OJ"]["Discuss"];
        mongocxx::pipeline pipe;

        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "Comments" << num
                << close_document;
        discusscoll.update_one(make_document(kvp("_id", articleId)),
                               document.view());
        return true;
    } catch (std::exception &e)
    {
        return false;
    }
}

Json::Value MoDB::SelectSolutionList(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t parentid = stoll(queryjson["SearchInfo"]["ParentId"].asString());
        int64_t userid = stoll(queryjson["SearchInfo"]["UserId"].asString());
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;

        Json::Reader reader;
        bsoncxx::builder::stream::document document{};
        mongocxx::pipeline pipe, pipetot;

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];

        if (parentid > 0)
        {
            // 匹配ID
            pipetot.match({make_document(kvp("ParentId", parentid))});
            pipe.match({make_document(kvp("ParentId", parentid))});

            // 匹配公开
            pipetot.match({make_document(kvp("Public", true))});
            pipe.match({make_document(kvp("Public", true))});
        }
        if (userid > 0)
        {
            // 匹配ID
            pipetot.match({make_document(kvp("UserId", userid))});
            pipe.match({make_document(kvp("UserId", userid))});
        }
        // 获取总条数

        pipetot.count("TotalNum");
        mongocxx::cursor cursor = solutioncoll.aggregate(pipetot);
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        pipe.sort({make_document(kvp("CreateTime", -1))});
        pipe.skip(skip);
        pipe.limit(pagesize);
        document
                << "from" << "User"
                << "localField" << "UserId"
                << "foreignField" << "_id"
                << "as" << "User";
        pipe.lookup(document.view());

        document.clear();
        document
                << "Title" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1
                << "User.Avatar" << 1
                << "User.NickName" << 1;
        pipe.project(document.view());

        cursor = solutioncoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            Json::Value jsonvalue;
            reader.parse(bsoncxx::to_json(doc), jsonvalue);
            resjson["ArrayInfo"].append(jsonvalue);
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::SelectSolutionListByAdmin(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;

        Json::Reader reader;
        bsoncxx::builder::stream::document document{};
        mongocxx::pipeline pipe, pipetot;

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];

        // 获取总条数
        pipetot.count("TotalNum");
        mongocxx::cursor cursor = solutioncoll.aggregate(pipetot);
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        pipe.sort({make_document(kvp("CreateTime", -1))});
        pipe.skip(skip);
        pipe.limit(pagesize);
        document
                << "from" << "User"
                << "localField" << "UserId"
                << "foreignField" << "_id"
                << "as" << "User";
        pipe.lookup(document.view());

        document.clear();
        document
                << "Title" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1
                << "UserId" << 1
                << "User.Avatar" << 1
                << "User.NickName" << 1;
        pipe.project(document.view());

        cursor = solutioncoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            Json::Value jsonvalue;
            reader.parse(bsoncxx::to_json(doc), jsonvalue);
            resjson["ArrayInfo"].append(jsonvalue);
        }
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::SelectSolutionByEdit(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t solutionid = stoll(queryjson["SolutionId"].asString());

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];

        bsoncxx::builder::stream::document document{};
        mongocxx::pipeline pipe;
        pipe.match({make_document(kvp("_id", solutionid))});
        document
                << "Title" << 1
                << "Content" << 1
                << "UserId" << 1
                << "Public" << 1;
        pipe.project(document.view());
        mongocxx::cursor cursor = solutioncoll.aggregate(pipe);

        Json::Reader reader;
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库未查询到数据！";
            return resjson;
        }
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::SelectSolution(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t solutionid = stoll(queryjson["SolutionId"].asString());

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];
        // 浏览量加一
        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "Views" << 1 << close_document;
        solutioncoll.update_one({make_document(kvp("_id", solutionid))}, document.view());

        // 查询Content
        mongocxx::pipeline pipe;
        pipe.match({make_document(kvp("_id", solutionid))});
        document.clear();

        document
                << "from" << "User"
                << "localField" << "UserId"
                << "foreignField" << "_id"
                << "as" << "User";
        pipe.lookup(document.view());

        document.clear();
        document
                << "Title" << 1
                << "Content" << 1
                << "Views" << 1
                << "Comments" << 1
                << "CreateTime" << 1
                << "UpdateTime" << 1
                << "User._id" << 1
                << "User.Avatar" << 1
                << "User.NickName" << 1;
        pipe.project(document.view());

        mongocxx::cursor cursor = solutioncoll.aggregate(pipe);

        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库未查询到数据！";
            return resjson;
        }
        Json::Reader reader;
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::InsertSolution(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t id = ++m_articleid;
        std::string title = queryjson["Title"].asString();
        std::string content = queryjson["Content"].asString();
        int64_t parentid = stoll(queryjson["ParentId"].asString());
        int64_t userid = stoll(queryjson["UserId"].asString());
        bool ispublic = queryjson["Public"].asBool();

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];
        bsoncxx::builder::stream::document document{};
        document
                << "_id" << id
                << "Title" << title
                << "Content" << content
                << "ParentId" << parentid
                << "UserId" << userid
                << "Views" << 0
                << "Comments" << 0
                << "Public" << ispublic
                << "CreateTime" << GetTime()
                << "UpdateTime" << GetTime();

        auto result = solutioncoll.insert_one(document.view());

        if ((*result).result().inserted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库插入失败！";
            return resjson;
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::UpdateSolution(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t solutionid = stoll(queryjson["SolutionId"].asString());
        std::string title = queryjson["Title"].asString();
        std::string content = queryjson["Content"].asString();
        bool ispublic = queryjson["Public"].asBool();

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];

        bsoncxx::builder::stream::document document{};
        document
                << "$set" << open_document
                << "Title" << title.data()
                << "Content" << content.data()
                << "Public" << ispublic
                << "UpdateTime" << GetTime().data()
                << close_document;

        solutioncoll.update_one({make_document(kvp("_id", solutionid))}, document.view());

        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::DeleteSolution(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t solutionid = stoll(queryjson["SolutionId"].asString());

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];

        auto result = solutioncoll.delete_one({make_document(kvp("_id", solutionid))});

        if ((*result).deleted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "数据库删除失败！";
            return resjson;
        }
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::UpdateSolutionComments(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t articleId = stoll(queryjson["ArticleId"].asString());
        int num = queryjson["Num"].asInt();

        auto client = pool.acquire();
        mongocxx::collection solutioncoll = (*client)["OJ"]["Solution"];
        mongocxx::pipeline pipe;

        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "Comments" << num
                << close_document;
        solutioncoll.update_one(make_document(kvp("_id", articleId)),
                                document.view());
        return true;
    } catch (std::exception &e)
    {
        return false;
    }
}

Json::Value MoDB::SelectCommentListByAdmin(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];

        mongocxx::pipeline pipe;
        bsoncxx::builder::stream::document document{};
        // 按照时间先后顺序
        pipe.sort({make_document(kvp("CreateTime", -1))});
        // 跳过多少条
        pipe.skip(skip);
        // 限制多少条
        pipe.limit(pagesize);

        // 选择需要的字段
        document
                << "ParentId" << 1
                << "ParentType" << 1
                << "Content" << 1
                << "CreateTime" << 1
                << "Child_Comments._id" << 1
                << "Child_Comments.Content" << 1
                << "Child_Comments.CreateTime" << 1;
        pipe.project(document.view());
        document.clear();

        Json::Reader reader;

        mongocxx::cursor cursor = commentcoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            Json::Value jsonvalue;
            reader.parse(bsoncxx::to_json(doc), jsonvalue);
            resjson["ArrayInfo"].append(jsonvalue);
        }
        resjson["TotalNum"] = std::to_string(commentcoll.count_documents({}));
        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::GetFatherComment(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t parentid = stoll(queryjson["ParentId"].asString());
        int sonnum = stoi(queryjson["SonNum"].asString());
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;
        int limit = pagesize;

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];

        mongocxx::pipeline pipe;
        bsoncxx::builder::stream::document document{};

        pipe.match(make_document(kvp("ParentId", parentid)));

        //获取Child_Total
        document
                << "$set" << open_document
                << "Child_Total" << open_document
                << "$size" << "$Child_Comments"
                << close_document
                << close_document;
        pipe.append_stage(document.view());

        //截取sonnum个子评论
        document.clear();
        document
                << "$set" << open_document
                << "Child_Comments" << open_document
                << "$slice" << open_array
                << "$Child_Comments" << 0 << sonnum
                << close_array
                << close_document
                << close_document;
        pipe.append_stage(document.view());

        document.clear();
        document
                << "path" << "$Child_Comments"
                << "preserveNullAndEmptyArrays" << true;
        pipe.unwind(document.view());

        document.clear();
        document
                << "from" << "User"
                << "localField" << "Child_Comments.UserId"
                << "foreignField" << "_id"
                << "as" << "Child_Comments.User";
        pipe.lookup(document.view());

        document.clear();
        document
                << "_id" << "$_id"
                << "ParentId" << open_document
                << "$first" << "$ParentId" << close_document
                << "Content" << open_document
                << "$first" << "$Content" << close_document
                << "Likes" << open_document
                << "$first" << "$Likes" << close_document
                << "UserId" << open_document
                << "$first" << "$UserId" << close_document
                << "CreateTime" << open_document
                << "$first" << "$CreateTime" << close_document
                << "Child_Total" << open_document
                << "$first" << "$Child_Total" << close_document
                << "Child_Comments" << open_document
                << "$push" << "$Child_Comments" << close_document;
        pipe.group(document.view());

        document.clear();
        document
                << "from" << "User"
                << "localField" << "UserId"
                << "foreignField" << "_id"
                << "as" << "User";
        pipe.lookup(document.view());

        // 按照时间先后顺序
        pipe.sort({make_document(kvp("CreateTime", 1))});
        // 跳过多少条
        pipe.skip(skip);
        // 限制多少条
        pipe.limit(limit);

        document.clear();
        document
                << "ParentId" << 1
                << "Content" << 1
                << "Likes" << 1
                << "CreateTime" << 1
                << "Child_Total" << 1
                << "User._id" << 1
                << "User.Avatar" << 1
                << "User.NickName" << 1
                << "Child_Comments._id" << 1
                << "Child_Comments.Content" << 1
                << "Child_Comments.Likes" << 1
                << "Child_Comments.CreateTime" << 1
                << "Child_Comments.User._id" << 1
                << "Child_Comments.User.Avatar" << 1
                << "Child_Comments.User.NickName" << 1;
        pipe.project(document.view());

        Json::Reader reader;

        mongocxx::cursor cursor = commentcoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            Json::Value jsonvalue;
            reader.parse(bsoncxx::to_json(doc), jsonvalue);
            resjson["ArryInfo"].append(jsonvalue);
        }
        resjson["TotalNum"] = std::to_string(commentcoll.count_documents({make_document(kvp("ParentId", parentid))}));
        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::GetSonComment(Json::Value &queryjson)
{
    Json::Value resjson;

    try
    {
        int64_t _id = stoll(queryjson["ParentId"].asString());
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];
        mongocxx::pipeline pipe;
        bsoncxx::builder::stream::document document{};
        // 匹配id
        pipe.match({make_document(kvp("_id", _id))});

        // 将子评论进行求个数
        document
                << "$set" << open_document
                << "Child_Total" << open_document
                << "$size" << "$Child_Comments"
                << close_document
                << close_document;

        pipe.append_stage(document.view());
        document.clear();
        // 限制子评论个数
        document
                << "$set" << open_document
                << "Child_Comments" << open_document
                << "$slice" << open_array
                << "$Child_Comments" << skip << pagesize << close_array
                << close_document << close_document;

        pipe.append_stage(document.view());
        document.clear();
        // 将数组拆散
        document
                << "path" << "$Child_Comments"
                << "preserveNullAndEmptyArrays" << true;
        pipe.unwind(document.view());
        document.clear();
        // 将子评论的用户id和用户表进行外连接
        document
                << "from" << "User"
                << "localField" << "Child_Comments.UserId"
                << "foreignField" << "_id"
                << "as" << "Child_Comments.User";
        pipe.lookup(document.view());
        document.clear();

        // 将其合并
        document
                << "_id" << "$_id"
                << "Child_Total" << open_document
                << "$first" << "$Child_Total" << close_document
                << "Child_Comments" << open_document
                << "$push" << "$Child_Comments" << close_document;
        pipe.group(document.view());
        document.clear();
        document
                << "Child_Total" << 1
                << "Child_Comments._id" << 1
                << "Child_Comments.Content" << 1
                << "Child_Comments.Likes" << 1
                << "Child_Comments.CreateTime" << 1
                << "Child_Comments.User._id" << 1
                << "Child_Comments.User.NickName" << 1
                << "Child_Comments.User.Avatar" << 1;
        pipe.project(document.view());
        document.clear();

        Json::Reader reader;

        mongocxx::cursor cursor = commentcoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        resjson["Result"] = "Success";
        resjson["Reason"] = "";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::InsertFatherComment(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t id = ++m_commentid;
        int64_t parentid = stoll(queryjson["ParentId"].asString());
        std::string parenttype = queryjson["ArticleType"].asString();
        std::string content = queryjson["Content"].asString();
        int64_t userid = stoll(queryjson["UserId"].asString());
        std::string createtime = GetTime();

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];
        bsoncxx::builder::stream::document document{};
        document
                << "_id" << id
                << "ParentId" << parentid
                << "ParentType" << parenttype
                << "Content" << content
                << "UserId" << userid
                << "Likes" << 0
                << "CreateTime" << createtime
                << "Child_Comments" << open_array
                << close_array;

        commentcoll.insert_one(document.view());
        resjson["_id"] = std::to_string(id);
        resjson["CreateTime"] = createtime.data();
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::InsertSonComment(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t parentid = stoll(queryjson["ParentId"].asString());
        int64_t id = ++m_commentid;
        std::string content = queryjson["Content"].asString();
        int64_t userid = stoll(queryjson["UserId"].asString());
        std::string createtime = GetTime();

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];

        bsoncxx::builder::stream::document document{};
        document
                << "$addToSet" << open_document
                << "Child_Comments" << open_document
                << "_id" << id
                << "Content" << content
                << "UserId" << userid
                << "Likes" << 0
                << "CreateTime" << createtime
                << close_document
                << close_document;

        commentcoll.update_one({make_document(kvp("_id", parentid))}, document.view());

        resjson["_id"] = std::to_string(id);
        resjson["CreateTime"] = createtime;
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::DeleteFatherComment(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t commentid = stoll(queryjson["CommentId"].asString());

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];
        bsoncxx::builder::stream::document document{};
        mongocxx::pipeline pipe;

        //先查询看是否能查询到父评论，若能，获取子评论数和ArticleType
        auto cursor = commentcoll.find(make_document(kvp("_id", commentid)));
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "查不到父评论！";
            return resjson;
        }

        //如果查到
        Json::Reader reader;
        Json::Value value;
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), value);
        }
        int deletenum = value["Child_Comments"].size() + 1;
        std::string articletype = value["ParentType"].asString();

        //删除
        auto result = commentcoll.delete_one(make_document(kvp("_id", commentid)));

        //如果没删除，返回fail
        if ((*result).result().deleted_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "删除评论失败";
            return resjson;
        }

        //返回DeleteNum和ArticleType
        resjson["DeleteNum"] = deletenum;
        resjson["ArticleType"] = articletype;
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::DeleteSonComment(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t commentid = stoll(queryjson["CommentId"].asString());

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];
        bsoncxx::builder::stream::document document{};
        mongocxx::pipeline pipe;

        //查找子评论对应的父评论
        auto cursor = commentcoll.find(make_document(kvp("Child_Comments._id", commentid)));
        if (cursor.begin() == cursor.end())
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "查不到子评论！";
            return resjson;
        }

        //如果查到
        Json::Reader reader;
        Json::Value value;
        for (auto &doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), value);
        }
        //设置ArticleType和DeleteNum
        int deletenum = 1;
        std::string articletype = value["ParentType"].asString();
        int64_t fatherid = value["_id"].asInt64();

        document.clear();
        document
                << "$pull" << open_document
                << "Child_Comments" << open_document
                << "_id" << commentid
                << close_document << close_document;

        //删除子评论
        auto result = commentcoll.update_one({make_document(kvp("_id", fatherid))}, document.view());

        //如果没删除，返回fail
        if ((*result).result().matched_count() < 1)
        {
            resjson["Result"] = "Fail";
            resjson["Reason"] = "删除评论失败";
            return resjson;
        }

        //返回DeleteNum和ArticleType
        resjson["DeleteNum"] = deletenum;
        resjson["ArticleType"] = articletype;
        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

bool MoDB::DeleteArticleComment(Json::Value &queryjson)
{
    try
    {
        int64_t articleid = stoll(queryjson["ArticleId"].asString());

        auto client = pool.acquire();
        mongocxx::collection commentcoll = (*client)["OJ"]["Comment"];
        auto result = commentcoll.delete_many({make_document(kvp("ParentId", articleid))});

        return true;
    } catch (const std::exception &e)
    {
        return false;
    }
}

std::string MoDB::InsertStatusRecord(Json::Value &queryjson)
{
    try
    {
        int64_t statusrecordid = ++m_statusrecordid;
        int64_t problemid = stoll(queryjson["ProblemId"].asString());
        int64_t userid = stoll(queryjson["UserId"].asString());
        std::string usernickname = queryjson["UserNickName"].asString();
        std::string problemtitle = queryjson["ProblemTitle"].asString();
        std::string code = queryjson["Code"].asString();
        std::string language = queryjson["Language"].asString();

        auto client = pool.acquire();
        mongocxx::collection statusrecordcoll = (*client)["OJ"]["StatusRecord"];
        bsoncxx::builder::stream::document document{};
        document
                << "_id" << statusrecordid
                << "ProblemId" << problemid
                << "UserId" << userid
                << "UserNickName" << usernickname
                << "ProblemTitle" << problemtitle
                << "Status" << 0
                << "Runtime" << "0MS"
                << "RunMemory" << "0MB"
                << "Length" << "0B"
                << "Language" << language
                << "SubmitTime" << GetTime()
                << "Code" << code
                << "ComplierInfo" << ""
                << "TestInfo" << open_array << close_array;

        statusrecordcoll.insert_one(document.view());

        return std::to_string(statusrecordid);
    } catch (const std::exception &e)
    {
        return "0";
    }
}

bool MoDB::UpdateStatusRecord(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t submitid = stoll(queryjson["SubmitId"].asString());
        int status = stoi(queryjson["Status"].asString());
        std::string runtime = queryjson["RunTime"].asString();
        std::string runmemory = queryjson["RunMemory"].asString();
        std::string length = queryjson["Length"].asString();
        std::string complierinfo = queryjson["ComplierInfo"].asString();

        // 更新测评记录
        auto client = pool.acquire();
        mongocxx::collection statusrecordcoll = (*client)["OJ"]["StatusRecord"];
        bsoncxx::builder::stream::document document{};
        auto in_array = document
                        << "$set" << open_document
                        << "Status" << status
                        << "RunTime" << runtime.data()
                        << "RunMemory" << runmemory.data()
                        << "Length" << length.data()
                        << "ComplierInfo" << complierinfo.data()
                        << "TestInfo" << open_array;

        for (unsigned int i = 0; i < queryjson["TestInfo"].size(); i++)
        {
            int teststatus = stoi(queryjson["TestInfo"][i]["Status"].asString());
            std::string standardinput = queryjson["TestInfo"][i]["StandardInput"].asString();
            std::string standardoutput = queryjson["TestInfo"][i]["StandardOutput"].asString();
            std::string personaloutput = queryjson["TestInfo"][i]["PersonalOutput"].asString();
            std::string testruntime = queryjson["TestInfo"][i]["RunTime"].asString();
            std::string testrunmemory = queryjson["TestInfo"][i]["RunMemory"].asString();
            in_array = in_array << open_document
                       << "Status" << teststatus
                       << "StandardInput" << standardinput
                       << "StandardOutput" << standardoutput
                       << "PersonalOutput" << personaloutput
                       << "RunTime" << testruntime
                       << "RunMemory" << testrunmemory << close_document;
        }
        bsoncxx::document::value doc = in_array << close_array << close_document << finalize;

        statusrecordcoll.update_one({make_document(kvp("_id", submitid))}, doc.view());

        return true;
    } catch (const std::exception &e)
    {
        return false;
    }
}

bool MoDB::UpdateProblemStatusNum(Json::Value &queryjson)
{
    try
    {
        int64_t problemid = stoll(queryjson["ProblemId"].asString());
        int status = stoi(queryjson["Status"].asString());

        std::string statusnum = "";
        if (status == CE)
            statusnum = "CENum";
        else if (status == AC)
            statusnum = "ACNum";
        else if (status == WA)
            statusnum = "WANum";
        else if (status == RE)
            statusnum = "RENum";
        else if (status == TLE)
            statusnum = "TLENum";
        else if (status == MLE)
            statusnum = "MLENum";
        else if (status == SE)
            statusnum = "SENum";

        auto client = pool.acquire();
        mongocxx::collection problemcoll = (*client)["OJ"]["Problem"];
        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "SubmitNum" << 1
                << statusnum << 1 << close_document;

        problemcoll.update_one({make_document(kvp("_id", problemid))}, document.view());
        return true;
    } catch (const std::exception &e)
    {
        return false;
    }
}

bool MoDB::UpdateUserProblemInfo(Json::Value &queryjson)
{
    try
    {
        int64_t userid = stoll(queryjson["UserId"].asString());
        int problemid = stoi(queryjson["ProblemId"].asString());
        int status = stoi(queryjson["Status"].asString());

        // 将用户提交数目加一
        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];

        bsoncxx::builder::stream::document document{};
        document
                << "$inc" << open_document
                << "SubmitNum" << 1 << close_document;

        usercoll.update_one({make_document(kvp("_id", userid))}, document.view());

        // 如果AC了
        if (status == AC)
        {
            // 查询AC题目是否已经添加至Solves的数组中
            mongocxx::pipeline pipe;
            pipe.match({make_document(kvp("_id", userid))});
            document.clear();
            document
                    << "IsHasAc" << open_document
                    << "$in" << open_array << problemid << "$Solves" << close_array
                    << close_document;
            pipe.project(document.view());
            Json::Reader reader;
            Json::Value tmpjson;
            mongocxx::cursor cursor = usercoll.aggregate(pipe);

            for (auto doc: cursor)
            {
                reader.parse(bsoncxx::to_json(doc), tmpjson);
            }
            // 如果未添加
            if (tmpjson["IsHasAc"].asBool() == false)
            {
                document.clear();
                document
                        << "$push" << open_document
                        << "Solves" << problemid
                        << close_document
                        << "$inc" << open_document
                        << "ACNum" << 1 << close_document;
                usercoll.update_one({make_document(kvp("_id", userid))}, document.view());
                return true;
            }
            return false;
        }
        return false;
    } catch (const std::exception &e)
    {
        return false;
    }
}

Json::Value MoDB::SelectStatusRecordList(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        Json::Value searchinfo = queryjson["SearchInfo"];
        int page = stoi(queryjson["Page"].asString());
        int pagesize = stoi(queryjson["PageSize"].asString());
        int skip = (page - 1) * pagesize;

        Json::Reader reader;
        mongocxx::pipeline pipe, pipetot;
        bsoncxx::builder::stream::document document{};
        auto client = pool.acquire();
        mongocxx::collection statusrecordcoll = (*client)["OJ"]["StatusRecord"];

        // 查询题目ID
        if (searchinfo["ProblemId"].asString().size() > 0)
        {
            int64_t problemid = stoll(searchinfo["ProblemId"].asString());
            pipe.match(make_document(kvp("ProblemId", problemid)));
            pipetot.match(make_document(kvp("ProblemId", problemid)));
        }
        // 查询用户ID
        if (searchinfo["UserId"].asString().size() > 0)
        {
            int64_t userid = stoll(searchinfo["UserId"].asString());
            pipe.match(make_document(kvp("UserId", userid)));
            pipetot.match(make_document(kvp("UserId", userid)));
        }

        // 查询题目标题
        if (searchinfo["ProblemTitle"].asString().size() > 0)
        {
            document
                    << "ProblemTitle" << open_document
                    << "$regex" << searchinfo["ProblemTitle"].asString()
                    << close_document;
            pipe.match(document.view());
            pipetot.match(document.view());
            document.clear();
        }

        // 查询状态
        if (searchinfo["Status"].asString().size() > 0)
        {
            int status = stoi(searchinfo["Status"].asString());
            pipe.match(make_document(kvp("Status", status)));
            pipetot.match(make_document(kvp("Status", status)));
        }

        // 查询语言
        if (searchinfo["Language"].asString().size() > 0)
        {
            std::string language = searchinfo["Language"].asString();
            pipe.match(make_document(kvp("Language", language)));
            pipetot.match(make_document(kvp("Language", language)));
        }
        // 获取总条数
        pipetot.count("TotalNum");
        mongocxx::cursor cursor = statusrecordcoll.aggregate(pipetot);
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }

        // 排序
        pipe.sort({make_document(kvp("SubmitTime", -1))});
        // 跳过
        pipe.skip(skip);
        // 限制
        pipe.limit(pagesize);

        document
                << "ProbleId" << 1
                << "UserId" << 1
                << "UserNickName" << 1
                << "ProblemTitle" << 1
                << "Status" << 1
                << "RunTime" << 1
                << "RunMemory" << 1
                << "Length" << 1
                << "Language" << 1
                << "SubmitTime" << 1;
        pipe.project(document.view());
        Json::Value arrayjson;
        cursor = statusrecordcoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            Json::Value jsonvalue;
            reader.parse(bsoncxx::to_json(doc), jsonvalue);
            arrayjson.append(jsonvalue);
        }
        resjson["ArrayInfo"] = arrayjson;
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::SelectStatusRecord(Json::Value &queryjson)
{
    Json::Value resjson;
    try
    {
        int64_t submitid = stoll(queryjson["SubmitId"].asString());
        auto client = pool.acquire();
        mongocxx::collection statusrecordcoll = (*client)["OJ"]["StatusRecord"];

        mongocxx::pipeline pipe;
        bsoncxx::builder::stream::document document{};

        pipe.match({make_document(kvp("_id", submitid))});

        document
                << "Status" << 1
                << "Language" << 1
                << "Code" << 1
                << "ComplierInfo" << 1
                << "TestInfo" << 1;

        pipe.project(document.view());
        // 查询测评记录
        Json::Reader reader;

        mongocxx::cursor cursor = statusrecordcoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            reader.parse(bsoncxx::to_json(doc), resjson);
        }
        resjson["Result"] = "Success";

        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}

Json::Value MoDB::SelectUserAuthority()
{
    Json::Value resjson;
    try
    {
        auto client = pool.acquire();
        mongocxx::collection usercoll = (*client)["OJ"]["User"];

        mongocxx::pipeline pipe;
        bsoncxx::builder::stream::document document{};

        document
                << "Authority" << 1;

        pipe.project(document.view());
        // 查询测评记录
        Json::Reader reader;

        mongocxx::cursor cursor = usercoll.aggregate(pipe);
        for (auto doc: cursor)
        {
            Json::Value value;
            reader.parse(bsoncxx::to_json(doc), value);
            resjson["ArrayInfo"].append(value);
        }

        resjson["Result"] = "Success";
        return resjson;
    } catch (const std::exception &e)
    {
        resjson["Result"] = "500";
        resjson["Reason"] = "数据库异常！";
        return resjson;
    }
}
